package com.jolink.omiis.wechat.inner;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonObject;
import com.jolink.omiis.wechat.SpringContextUtil;
import com.jolink.omiis.wechat.api.CSMessageBuilder;
import com.jolink.omiis.wechat.api.IMaterialApi;
import com.jolink.omiis.wechat.api.IWeChatBrokerMessage;
import com.jolink.omiis.wechat.keys.IPreferences;
import com.jolink.omiis.wechat.message.Encryption;
import com.jolink.omiis.wechat.message.type.MessageType;
import com.jolink.omiis.wechat.mongo.IMongodbProcessor;
import com.jolink.omiis.wechat.redis.IRedisProcessor;
import com.jolink.omiis.wechat.util.CacheUtil;
import com.jolink.omiis.wechat.util.DateUtil;
import com.jolink.omiis.wechat.util.FileUtil;
import com.jolink.omiis.wechat.util.GsonUtil;
import com.jolink.omiis.wechat.util.WeChatConfiguration;

/**
 * 全媒体Server推送消息至微信开放平台，回调接口类
 * 
 * @author WangYanqing
 *
 */
public class OmiisResponseMessageHandler extends ResponseMessageHandler {
	private static Logger logger = LoggerFactory.getLogger(OmiisResponseMessageHandler.class);
	private String downloadTempPath = IPreferences.DOWNLOAD_TEMP_PATH;

	public OmiisResponseMessageHandler() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * 消息回调接口
	 * 
	 * @see io.socket.emitter.Emitter.Listener#call(java.lang.Object[])
	 */
	@Override
	public void call(Object... args) {
		if (ArrayUtils.isEmpty(args)) {
			return;
		}
		// String firstKey = "xxx";
		// String secondKey = "yyy";
		// String thirdKey = "zzz";
		String decryptMessage = null;
		if (args[0] instanceof String) {
			Encryption encrypt = new Encryption();
			decryptMessage = encrypt.decrypt((String) args[0], IOmiisMessager.KEY_1, IOmiisMessager.KEY_2,
					IOmiisMessager.KEY_3);
		}
		// JSONObject jsonObject = (JSONObject) args[0];
		logger.info("密文：{}，消息解密后：{}。", (String) args[0], decryptMessage);
		BusMessage busMessage = GsonUtil.json2Object(decryptMessage, BusMessage.class);
		// BusMessage busMessage = GsonUtil.json2Object(jsonObject.toString(),
		// BusMessage.class);
		String msgType = busMessage.getMsgType();
		ConversationType ct = ConversationType.valueOf(msgType);
		logger.info("接收到全媒体Serve信息，消息类型：{}，内容：{}。", msgType, decryptMessage);
		switch (ct) {
		case EVENT_REGISTER_COMPLETED:
			logger.info("微信渠道注册成功。");
			break;
		case TEXT:
			processTextMessage(busMessage);
			break;
		case AUDIO:
			processVoiceMessage(busMessage);
			break;
		case VIDEO:
			processVideoMessage(busMessage);
			break;
		case IMAGE:
			processImageMessage(busMessage);
			break;
		case EVENT_TALK:
			processEventTalk(busMessage);
			break;
		case EVENT_WAITING:
			processEventWaiting(busMessage);
			break;
		case EVENT_QUEUE_UPDATE:
			// TODO 排队数更新
			break;
		case EVENT_HANGUP_ARRIVED:
			// TODO 收到客服人员发起的挂机事件
			// processEventHangupArrived(busMessage);
			// 20161219 坐席挂断操作变更为
			processSatisfactionSurvey(busMessage);
			break;
		case EVENT_HANGUP_COMPLETED:
			// TODO 客户自己发起了挂机请求，服务器反馈挂机成功
			break;
		case EVENT_DISCONNECT_ARRIVED:
			// TODO 客服人员掉线
			processEventDisconnectArrived(busMessage);
			break;
		case EVENT_TRANSFER_ARRIVED:
			// TODO 客服人员把客户的对话转接给其它客服人员
			processEventTransferArrived(busMessage);
			break;
		case EVENT_CONFERENCE_ARRIVED:
			// TODO 有第三方加入到对话中
			processEventConferenceArrived(busMessage);
			break;
		case EVENT_MONITOR_ARRIVED:
			// TODO 监听事件到达（注：需要在receiverId中，增加监听者的ID。多ID之前通过逗号","分隔）
			processEventMonitorArrived(busMessage);
			break;
		case EVENT_MONITOR_RELEASED:
			// TODO 释放监听（注：需要在receiverId中，移除监听者的ID。）
			processEventMonitorReleased(busMessage);
			break;
		case EVENT_TAKEOVER_ARRIVED:
			// TODO 接管事件到达（注：除了在界面中知会客户外，还需要更新receiverId。）
			processEventTakeoverArrived(busMessage);
			break;
		case EVENT_INTERVENE_ARRIVED:
			// TODO 介入事件到达
			processEventInterveneArrived(busMessage);
			break;
		case SATISFACTION_SURVEY:
			processSatisfactionSurvey(busMessage);
			break;
		}
	}

	/**
	 * 
	 * 会议事件
	 * 
	 * @param bm
	 */
	private void processEventConferenceArrived(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理会议事件，信息：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			String agentIds = userSessionInfo.get("receiverId");
			StringBuffer tmp = new StringBuffer();
			if (!StringUtils.isEmpty(agentIds)) {
				if (!agentIds.contains(bm.getMsgContent())) {
					tmp.append(agentIds).append(",").append(bm.getMsgContent());
				} else {
					tmp.append(agentIds.toString());
				}
			} else {
				tmp.append(bm.getSenderId()).append(",").append(bm.getMsgContent());
			}

			userSessionInfo.put("receiverId", tmp.toString());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", bm.getReceiverId());// 微信用户
			logger.info("更新sessionId：{}，会话信息：{}。", sessionId, userSessionInfo);
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					getContext().getServiceUtil().getExpression().getEventConferenceTip(bm.getMsgContent())));
			// logger.info("客服：{}，加入会议：{}，客服人员：{}。", bm.getMsgContent(),
			// userSessionInfo, tmp.toString());
			logger.info("客服：{}，加入会议，通知微信用户：{}，客服人员：{}，会话信息：{}，。", bm.getMsgContent(), bm.getReceiverId(),
					tmp.toString(), userSessionInfo);
		} catch (Exception e) {
			logger.info(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理加入会议事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 介入事件
	 * 
	 * @param bm
	 */
	private void processEventInterveneArrived(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理介入对话事件，信息：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			String agentIds = userSessionInfo.get("receiverId");
			StringBuffer tmp = new StringBuffer();
			if (!StringUtils.isEmpty(agentIds)) {
				if (!agentIds.contains(bm.getSenderId())) {
					tmp.append(agentIds).append(",").append(bm.getSenderId());
				} else {
					tmp.append(agentIds.toString());
				}
			} else {
				tmp.append(bm.getSenderId()).append(",").append(bm.getMsgContent());
			}

			// logger.info("坐席：{}，介入对话：{}，坐席人员：{}。", bm.getSenderId(),
			// userSessionInfo, tmp.toString());
			userSessionInfo.put("receiverId", tmp.toString());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", bm.getReceiverId());// 微信用户
			logger.info("更新sessionId：{}，会话信息：{}。", sessionId, userSessionInfo);
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					getContext().getServiceUtil().getExpression().getEventInterveneTip(bm.getSenderId())));
			logger.info("客服：{}，介入会话，通知微信用户：{}，客服人员：{}，会话信息：{}，。", bm.getSenderId(), bm.getReceiverId(), tmp.toString(),
					userSessionInfo);
		} catch (Exception e) {
			logger.info(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理介入对话事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 
	 * 监控
	 * 
	 * @param bm
	 */
	private void processEventMonitorArrived(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理监听对话事件，信息：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			String agentIds = userSessionInfo.get("receiverId");
			StringBuffer tmp = new StringBuffer();
			if (!StringUtils.isEmpty(agentIds)) {
				if (!agentIds.contains(bm.getSenderId())) {
					tmp.append(agentIds).append(",").append(bm.getSenderId());
				} else {
					tmp.append(agentIds.toString());
				}
			} else {
				tmp.append(bm.getSenderId());
			}
			// logger.info("坐席：{}，监听对话：{}，坐席人员：{}。", bm.getSenderId(),
			// userSessionInfo, tmp.toString());
			userSessionInfo.put("receiverId", tmp.toString());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", openId);// 微信用户
			logger.info("更新sessionId：{}，会话信息：{}。", sessionId, userSessionInfo);
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			logger.info("客服：{}，监听会话，通知微信用户：{},客服人员：{}，会话信息：{}。", bm.getSenderId(), bm.getReceiverId(), tmp.toString(),
					userSessionInfo);
		} catch (Exception e) {
			logger.info(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理监听对话事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * @param bm
	 */
	private void processEventMonitorReleased(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理取消监听对话事件，信息：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			String agentIds = userSessionInfo.get("receiverId");
			StringBuffer tmp = new StringBuffer();
			if (!StringUtils.isEmpty(agentIds)) {
				List<String> agentList = Arrays.asList(agentIds.toString().split(","));
				logger.info("检查坐席：{}是否在会话坐席列表中{}。", bm.getSenderId(), agentIds);
				if (agentList.contains(bm.getSenderId())) {
					logger.info("坐席：{}在会话中坐席列表中，将其移除。");
					agentList.remove(bm.getSenderId());
				}
				tmp.append(Arrays.toString(agentList.toArray(new String[] {})));
			} else {
				logger.error("监控异常发生，信息：{}。", bm.toString());
				// tmp.append(bm.getSenderId()).append(",").append(bm.getMsgContent());
			}
			logger.info("坐席：{}，监听对话：{}，坐席人员：{}。", bm.getSenderId(), userSessionInfo, tmp.toString());
			userSessionInfo.put("receiverId", tmp.toString());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", openId);// 微信用户
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			logger.info("客服：{}，取消监听该会话，更新会话信息：{}。", bm.getSenderId(), userSessionInfo, bm.getReceiverId());
		} catch (Exception e) {
			logger.info(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理取消监听对话事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 接管事件
	 * 
	 * @param bm
	 */
	private void processEventTakeoverArrived(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理坐席接管事件，内容：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", openId);// 微信用户
			// 20161121 update by wangyq 坐席接管服务，需要重新绑定至新客服，解除旧有坐席绑定关系
			redis.sadd(CacheUtil.getAgentKey(bm.getSenderId()), openId);
			redis.sadd(IPreferences.AGENT_SET, bm.getSenderId());
			redis.srem(CacheUtil.getAgentKey(userSessionInfo.get("receiverId")), openId);
			userSessionInfo.put("receiverId", bm.getSenderId());// 坐席
			send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					getContext().getServiceUtil().getExpression().getTakeoverTip(bm.getSenderId())));
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			{
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("agentId", "");
				deltaSessionInfo.put("openId", openId);
				deltaSessionInfo.put("direction", "agent");
				deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				deltaSessionInfo.put("customer_previous_message_timestamp",
						deltaSessionInfo.get("agent_previous_message_timestamp"));
				getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
			}
			logger.info("现在由客服：{}，接管会话，通知微信用户：{}，更新会话信息：{}。", bm.getSenderId(), bm.getReceiverId(), userSessionInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理坐席接管事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 
	 * 转接事件
	 * 
	 * @param bm
	 */
	private void processEventTransferArrived(BusMessage bm) {
		long t1 = System.currentTimeMillis();
		logger.info("开始处理转接事件，内容：{}。", bm.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}

			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", openId);// 微信用户
			// 20161121 update by wangyq 坐席接管服务，需要重新绑定至新客服，解除旧有坐席绑定关系
			redis.sadd(CacheUtil.getAgentKey(bm.getMsgContent()), openId);
			redis.sadd(IPreferences.AGENT_SET, bm.getMsgContent());
			redis.srem(CacheUtil.getAgentKey(userSessionInfo.get("receiverId")), openId);
			redis.srem(CacheUtil.getAgentKey(bm.getSenderId()), openId);
			userSessionInfo.put("receiverId", bm.getMsgContent());// 坐席
			send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					getContext().getServiceUtil().getExpression().getTakeoverTip(bm.getMsgContent())));
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			logger.info("现在由客服：{}，服务会话，通知微信用户：{}，更新会话信息：{}。", bm.getMsgContent(), bm.getReceiverId(), userSessionInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理转接事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 处理坐席断开事件
	 * 
	 * @param busMessage
	 */
	private void processEventDisconnectArrived(BusMessage busMessage) {
		long t1 = System.currentTimeMillis();
		logger.info("处理全媒体坐席离线事件：{}。", busMessage.toString());
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		String agentKey = CacheUtil.getAgentKey(busMessage.getSenderId());
		Set<String> userSet = null;
		try {
			userSet = redis.smembers(agentKey);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		if (userSet == null || userSet.isEmpty()) {
			logger.info("坐席：{}，当前未服务微信用户。");
			return;
		}
		logger.info("坐席：{}，服务的微信用户：{}。", busMessage.getSenderId(), userSet);
		for (Iterator<String> it = userSet.iterator(); it.hasNext();) {
			String openId = it.next();
			try {
				Map<String, String> userBaseInfo = redis.hgetall(CacheUtil.getUserKey(openId));
				if (!checkSessionValid(userBaseInfo)) {
					continue;
				}
				String session_id = userBaseInfo.get("session_id");
				if (StringUtils.isEmpty(session_id)) {
					logger.info("微信用户：{}不在会话中。", openId);
					continue;
				}
				Map<String, String> userSessionInfo = redis.hgetall(CacheUtil.getSessionKey(session_id));
				logger.info("微信用户：{}，基本信息：{}，会话信息：{}。", openId, userBaseInfo, userSessionInfo);
				String receiverId = userSessionInfo.get("receiverId");
				if (receiverId.split(",").length > 1) {
					logger.info("有其他坐席加入该会话：{}。", receiverId);
					List<String> agentList = Arrays.asList(receiverId.split(","));
					if (!agentList.contains(busMessage.getSenderId())) {
						continue;
					}
				} else if (!receiverId.equals(busMessage.getSenderId())) {
					continue;
				}
				logger.info("将微信用户：{}会话状态重置，会话ID：{}，并通知微信用户坐席离线。", openId, session_id);
				String message = CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
						getContext().getServiceUtil().getExpression().getAgentDisconnectTip());
				send(userBaseInfo.get("app_id"), message);
				redis.hdel(CacheUtil.getUserKey(openId), "session_id");
				getContext().getServiceUtil().getSessionManager().removeSession(openId);
				redis.del(agentKey);
				logger.info("清除坐席：{}维护的微信用户信息。", agentKey);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理全媒体坐席离线事件完成，耗时：{}毫秒。", (t2 - t1));
	}

	/**
	 * 发送微信用户信息的统一入口 1.发送消息目前存在两种场景 1.1公众号授权给三方平台，调用客服接口发送
	 * 1.2公众号后台转发消息，通过中继服务接口发送消息 1.3公众号转发的消息是获取不到appid，暂时此方法根据appid的是否为空为条件
	 * 1.4appid为空通过中继接口发送，相反通过客服消息接口发送
	 * 
	 * @param appId
	 * @param message
	 */
	private void send(String appId, String message) {
		long t1 = System.currentTimeMillis();
		logger.info("调用腾讯客服接口发送信息，appId：{}，message：{}。", appId, message);
		String result = null;
		if (StringUtils.isEmpty(appId)) {
			IWeChatBrokerMessage broker = SpringContextUtil.getBean(IWeChatBrokerMessage.class);
			broker.response(message);
		} else {
			// ICustomerService cs =
			// SpringContextUtil.getBean(ICustomerService.class);
			result = getContext().getServiceUtil().getCustomerService().send(appId, message);
		}
		long t2 = System.currentTimeMillis();
		logger.info("调用腾讯客服接口发送信息完成，结果：{}，耗时：{}毫秒。", result, (t2 - t1));
	}

	/**
	 * 暂时不用 update by wangyq 20161223
	 * 
	 * @param bm
	 */
	private void processEventHangupArrived(BusMessage bm) {
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			logger.info("全媒体客服发起会话挂断事件，信息{}。", bm);
			String openId = redis.get(bm.getReceiverId());
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}。", bm.getSenderId(), openId, userBaseInfo);
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			// userSessionInfo.put("receiverId", bm.getReceiverId());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			String content = getContext().getServiceUtil().getExpression().getHangupTip();
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", openId);// 微信用户
			userSessionInfo.put("conversation_type", ConversationType.HANGUP.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			redis.hdel(CacheUtil.getUserKey(openId), "session_id");
			redis.srem(CacheUtil.getAgentKey(bm.getSenderId()), openId);
			send(userBaseInfo.get("app_id"),
					CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), content));
			logger.info("客服：{}，主动结束会话，通知微信用户：{}，会话信息：{}。", bm.getSenderId(), bm.getReceiverId(), userSessionInfo);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 坐席接入通知
	 * 
	 * @param bm
	 */
	private void processEventTalk(BusMessage bm) {
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		if (getContext() == null) {
			logger.error("WechatContext为null");
			return;
		}
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getSenderId());
			logger.info("微信用户：{}，userid：{}，由客服：{}接入，详细信息{}。", openId, bm.getSenderId(), bm.getReceiverId(), bm);
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get(IPreferences.SESSION_ID_KEY);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getSenderId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("receiverId", bm.getReceiverId());// 坐席
			userSessionInfo.put("msgType", bm.getMsgType());
			String content = getContext().getServiceUtil().getExpression().getEventTalkTip(bm.getReceiverId());
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("sender_id", bm.getSenderId());// 微信用户
			userSessionInfo.put("conversation_type", ConversationType.EVENT_TALK.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			// 20161213 update by wangyq 接入会话，更新会话时间，开始计时
			{
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("agentId", bm.getReceiverId());
				deltaSessionInfo.put("openId", openId);
				deltaSessionInfo.put("direction", "agent");
				deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				deltaSessionInfo.put("customer_previous_message_timestamp",
						deltaSessionInfo.get("agent_previous_message_timestamp"));
				getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
			}
			// 20161118 update by
			// wangyq，全媒体坐席窗口关闭，发送断开事件至微信端，微信需维护坐席-为用户的列表，以便清理会话信息
			redis.sadd(CacheUtil.getAgentKey(bm.getReceiverId()), openId);
			redis.sadd(IPreferences.AGENT_SET, bm.getReceiverId());
			// ----------end
			send(userBaseInfo.get("app_id"),
					CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), content));
			logger.info("并通知微信用户：{}，客服接入，更新微信用户会话信息：{}，通知内容：{}。", bm.getSenderId(), userSessionInfo, content);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 处理客服推送的满意度请求 满意度类型需全媒体提供？
	 * 
	 * @param bm
	 */
	private void processSatisfactionSurvey(BusMessage bm) {
		logger.info("客服发送满意度调查请求，BusMessage：{}。", bm);
		String satisfactionSurveyMessage = getContext().getServiceUtil().getExpression().getSatisfactionSurveyMessage();
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				logger.info("该种情况发生的可能是因为坐席超时。");
				return;
			}
			String sessionId = userBaseInfo.get("session_id");
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("sender_id", bm.getReceiverId());
			userSessionInfo.put("conversationId", bm.getConversationId() == null ? "" : bm.getConversationId());
			userSessionInfo.put("conversation_type", ConversationType.SATISFACTION_SURVEY.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			// 20161213 update by wangyq，此处更新跟踪时间，统计未回复满意度
			{
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("agentId", bm.getSenderId());
				deltaSessionInfo.put("openId", openId);
				deltaSessionInfo.put("direction", "agent");
				deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
			}
			logger.info("调用全媒体接口更新微信用户：{}为满意度未评价。", openId);
			try {
				String host = WeChatConfiguration.getIngleton().getString("OMIIS_SERVER_HOST", "localhost");
				String uri = "http://" + host + ":7003/modifyinfo/investigation/update";
				List<NameValuePair> formData = new ArrayList<>();
				formData.add(new BasicNameValuePair("conversationId", userSessionInfo.get("conversationId")));
				formData.add(new BasicNameValuePair("grade", "NO_JUDGE"));
				UrlEncodedFormEntity urlEncodeFormEntity = new UrlEncodedFormEntity(formData, HTTP.UTF_8);
				executePost2(uri, "", urlEncodeFormEntity);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			redis.srem(CacheUtil.getAgentKey(bm.getSenderId()), openId);
			logger.info("坐席结束对话，推送满意度，解除微信用户：{}与坐席：{}的绑定关系。", bm.getSenderId(), openId);
			send(userBaseInfo.get("app_id"), CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(),
					satisfactionSurveyMessage.toString()));
			logger.info("推送满意度评价至微信用户：{}，更新会话信息：{}，通知内容：{}。", openId, userSessionInfo,
					satisfactionSurveyMessage.toString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 检查会话是否有效
	 * 
	 * @param userBaseInfo
	 * @return
	 */
	private boolean checkSessionValid(Map<String, String> userBaseInfo) {
		String sessionId = userBaseInfo.get("session_id");
		if (StringUtils.isEmpty(sessionId)) {
			logger.warn("会话ID不存在，请确认。", sessionId);
			return false;
		}
		return true;
	}

	/**
	 * 全媒体发送当前坐席繁忙通知
	 * 
	 * @param bm
	 */
	private void processEventWaiting(BusMessage bm) {
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			logger.info("收到当前坐席繁忙通知，BusMessage：{}。", bm);
			String openId = redis.get(bm.getSenderId());
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get("session_id");
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getSenderId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("receiverId", bm.getReceiverId() == null ? "" : bm.getReceiverId());
			userSessionInfo.put("msgType", bm.getMsgType());
			StringBuffer content = new StringBuffer();
			content.append(getContext().getServiceUtil().getExpression().getQueueTimeoutTip());
			userSessionInfo.put("sender_id", bm.getSenderId());
			userSessionInfo.put("conversationId", bm.getConversationId() == null ? "" : bm.getConversationId());
			userSessionInfo.put("conversation_type", ConversationType.EVENT_WAITING.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			{
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("agentId", "");
				deltaSessionInfo.put("openId", openId);
				deltaSessionInfo.put("direction", "agent");
				deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				deltaSessionInfo.put("customer_previous_message_timestamp",
						deltaSessionInfo.get("agent_previous_message_timestamp"));
				getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
			}
			{
				try {
					Map<String, Object> mongoMessage = new HashMap<>();
					mongoMessage.put("userId", userSessionInfo.get("user_id"));
					mongoMessage.put("channelId", IPreferences.CHANNEL_ID);
					mongoMessage.put("conversationId", userSessionInfo.get("conversationId"));
					mongoMessage.put("question", "");
					mongoMessage.put("receiveTime", new Date());
					mongoMessage.put("sendTime", mongoMessage.get("receiveTime"));
					// JsonObject root = new JsonObject();
					// root.addProperty("rspCode", "0");
					// root.addProperty("rspMsg", "");
					// root.addProperty("rspType", "2");
					// root.addProperty("conversationId",
					// userSessionInfo.get("conversationId"));
					// root.addProperty("singleNode", "");
					// JsonObject singleNode = new JsonObject();
					// root.add("singleNode", singleNode);
					// singleNode.addProperty("type", "1");
					// singleNode.addProperty("content", content.toString());
					JsonObject root = new JsonObject();
					root.addProperty("protocolId", "6");
					root.addProperty("result", "0");
					root.addProperty("sendTime", "0");
					root.addProperty("answerTypeId", "1");
					JsonObject singleNode = new JsonObject();
					singleNode.addProperty("standardQuestionId", "100");
					singleNode.addProperty("answerMsg", content.toString());
					singleNode.addProperty("standardQuestion", "");
					singleNode.addProperty("isRichText", "0");
					singleNode.add("list", null);
					root.add("singleNode", singleNode);
					root.add("vagueNode", null);
					mongoMessage.put("robotResponse", root.toString());
					mongoMessage.put("createDate", mongoMessage.get("receiveTime"));
					IMongodbProcessor processor = SpringContextUtil.getBean(IMongodbProcessor.class);
					processor.insertOne(IPreferences.MONGODB_ROBOTMESSAGE, mongoMessage);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			}
			send(userBaseInfo.get("app_id"),
					CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), content.toString()));
			logger.info("通知微信用户：{} 当前坐席繁忙，用户信息{}，更新会话信息：{}，通知内容：{}。", userBaseInfo.get("openid"), userBaseInfo,
					userSessionInfo, content.toString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 
	 * 检查微信用户会话状态
	 * 
	 * @param userSessionInfo
	 * @return
	 */
	private static boolean checkUserSessionState(Map<String, String> userSessionInfo) {
		String conversationType = userSessionInfo.get("conversation_type");
		if (ConversationType.SATISFACTION_SURVEY.getValue().equals(conversationType)
				|| ConversationType.HANGUP.getValue().equals(conversationType)) {
			return false;
		}
		return true;
	}

	/**
	 * 全媒体发送文本信息
	 * 
	 * @param bm
	 */
	private void processTextMessage(BusMessage bm) {
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get("session_id");
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			if (!checkUserSessionState(userSessionInfo)) {
				logger.info("微信用户：{}，会话状态为：{}，坐席消息不发送至微信用户。");
				return;
			}

			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("sender_id", openId);
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("conversation_type", ConversationType.EVENT_TALK.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			{
				if (!IPreferences.AUTO_SENDER_KEY.equals(bm.getSenderId())) {
					Map<String, String> deltaSessionInfo = new HashMap<String, String>();
					deltaSessionInfo.put("agentId", bm.getSenderId());
					deltaSessionInfo.put("openId", openId);
					deltaSessionInfo.put("direction", "agent");
					deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
					getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
				}
			}
			send(userBaseInfo.get("app_id"),
					CSMessageBuilder.createMessage(openId, MessageType.TEXT.getValue(), bm.getMsgContent()));
			logger.info("微信用户：{}，接收到全媒体客服信息，转发至微信用户，内容：{}。", openId, bm.getMsgContent());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 全媒体发送图片信息
	 * 
	 * @param bm
	 */
	private void processImageMessage(BusMessage bm) {
		Map<String, String> userBaseInfo = new HashMap<String, String>();
		Map<String, String> userSessionInfo = new HashMap<String, String>();
		IRedisProcessor redis = getContext().getServiceUtil().getRedisProcessor();
		try {
			String openId = redis.get(bm.getReceiverId());
			userBaseInfo.putAll(redis.hgetall(CacheUtil.getUserKey(openId)));
			if (!checkSessionValid(userBaseInfo)) {
				return;
			}
			String sessionId = userBaseInfo.get("session_id");
			if (!checkUserSessionState(userSessionInfo)) {
				logger.info("微信用户：{}，会话状态为：{}，坐席消息不发送至微信用户。");
				return;
			}
			logger.info("获取user_id：{}，对应的open_id：{}，基本信息：{}，会话信息：{}。", bm.getReceiverId(), openId, userBaseInfo,
					userSessionInfo);
			String msgContent = bm.getMsgContent();
			int lastSlashIndex = msgContent.lastIndexOf("/");
			String filename = msgContent.substring(lastSlashIndex + 1);
			logger.info("下载图片至临时路径，图片信息，URL：{}，文件名：{}，临时下载路径：{}。", msgContent, filename, downloadTempPath);
			FileUtil.download(msgContent, filename, downloadTempPath);
			logger.info("下载图片至临时路径完成，上传图片至腾讯素材库......");
			IMaterialApi material = SpringContextUtil.getBean(IMaterialApi.class);
			String result = material.uploadImage(userBaseInfo.get("app_id"),
					downloadTempPath + File.separator + filename);
			Map<String, String> resultMap = GsonUtil.str2Map(result);
			if (resultMap.isEmpty() || resultMap.containsKey("errcode")) {
				logger.error("上传图片至腾讯素材库失败，错误信息：", resultMap);
				return;
			}
			String retMediaId = resultMap.get("media_id");
			logger.info("上传图片至腾讯素材库完成，结果：{}，mediaId:{}。", result, retMediaId);
			userSessionInfo.putAll(redis.hgetall(CacheUtil.getSessionKey(sessionId)));
			String receiverIds = userSessionInfo.get("receiverId");// 坐席
			if (!StringUtils.isEmpty(receiverIds)) {
				List<String> agentList = Arrays.asList(receiverIds.split(","));
				if (!agentList.contains(bm.getSenderId())) {
					userSessionInfo.put("receiverId", receiverIds + "," + bm.getSenderId());
				}
			} else {
				userSessionInfo.put("receiverId", bm.getSenderId());
			}
			userSessionInfo.put("msgType", bm.getMsgType());
			userSessionInfo.put("sender_id", bm.getReceiverId());// 访客
			userSessionInfo.put("conversationId", bm.getConversationId());
			userSessionInfo.put("conversation_type", ConversationType.EVENT_TALK.getValue());
			redis.hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
			Map<String, String> deltaSessionInfo = new HashMap<String, String>();
			deltaSessionInfo.put("agentId", bm.getSenderId());
			deltaSessionInfo.put("openId", openId);
			deltaSessionInfo.put("direction", "agent");
			deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
			getContext().getServiceUtil().getSessionManager().updateSession(openId, deltaSessionInfo);
			send(userBaseInfo.get("app_id"),
					CSMessageBuilder.createMessage(openId, MessageType.IMAGE.getValue(), retMediaId));
			logger.info("微信用户：{}接收到全媒体客服发送图片信息，转发至微信用户，内容：{}。", openId, retMediaId);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 全媒体发送音频消息
	 * 
	 * @param bm
	 */
	private void processVoiceMessage(BusMessage bm) {
		logger.info("客服发送语音信息：{}，暂不处理，好像也不会发，哈哈！", bm.toString());
	}

	/**
	 * 全媒体发送音乐消息
	 * 
	 * @param bm
	 */
	private void processMusicMessage(BusMessage bm) {
		logger.info("客服发送音乐信息：{}，暂不处理，好像也不会发，哈哈！", bm.toString());
	}

	/**
	 * 全媒体发送视频消息
	 * 
	 * @param bm
	 */
	private void processVideoMessage(BusMessage bm) {
		logger.info("客服发送视频信息：{}，暂不处理，好像也不会发，哈哈！", bm.toString());
	}
}
